package com.qsw.extendedittext.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.text.Editable;
import android.text.InputFilter;
import android.text.InputType;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.text.method.DigitsKeyListener;
import android.util.AttributeSet;
import android.widget.EditText;

import com.qsw.extendedittext.R;
import com.qsw.extendedittext.view.listener.OnInputCheckSuccessListener;

import java.util.ArrayList;
import java.util.List;

/**
 * 支持分隔符的EditText
 */
public class DivideEditText extends EditText {

    public static final int TYPE_CUSTOM = 0;    // 类型：自定义
    public static final int TYPE_PHONE = 1;     // 类型：手机号
    public static final int TYPE_BANKCARD = 2;  // 类型：银行卡号
    public static final int TYPE_IDCARD = 3;    // 类型：身份证号
    public static final int TYPE_ISBN = 4;      // 类型：书籍ISBN

    private int mMaxLength = 20;// 支持输入的最大字符
    private int mWithoutDivideLength = 20;// 不包含分隔符的文本长度
    private int mContentType;// 输入类型

    private String mDivideStr = " ";// 分隔符
    private String mFormatStr;// 格式字符串

    private final List<Integer> mDivideIndexList = new ArrayList<>();// 需要添加分隔符的索引，在该索引对应的字符后边添加一个分隔符，该索引为不包含分隔符的原始字符串索引值

    private OnInputCheckSuccessListener mOnInputCheckSuccessListener;

    public DivideEditText(Context context) {
        this(context, null);
    }

    public DivideEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        parseAttributeSet(context, attrs);
    }

    public DivideEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        parseAttributeSet(context, attrs);
    }

    /**
     * 解析xml属性
     *
     * @param context 环境
     * @param attrs   属性集
     */
    private void parseAttributeSet(Context context, AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.DivideEditText, 0, 0);
        mContentType = typedArray.getInt(R.styleable.DivideEditText_edit_type, 0);
        String divide = typedArray.getString(R.styleable.DivideEditText_edit_divide);
        if (!TextUtils.isEmpty(divide)) {
            mDivideStr = divide;
        }
        mFormatStr = typedArray.getString(R.styleable.DivideEditText_edit_format);
        typedArray.recycle();

        initContentType();
        setSingleLine();
        addTextChangedListener(mTextWatcher);
    }

    /**
     * 解析格式
     *
     * @param formatStr 格式字符串
     */
    private void parseFormat(String formatStr) {
        // 格式中的分隔符
        if (TextUtils.isEmpty(formatStr)) {
            return;
        }
        StringBuilder sbFormat = new StringBuilder(formatStr);
        char formatDivide = '*';
        while (sbFormat.charAt(0) == formatDivide) {
            sbFormat.delete(0, 1);
            if (sbFormat.length() == 0) {
                return;
            }
        }
        while (sbFormat.charAt(sbFormat.length() - 1) == formatDivide) {
            sbFormat.delete(sbFormat.length() - 1, sbFormat.length());
            if (sbFormat.length() == 0) {
                return;
            }
        }

        mMaxLength = sbFormat.length();
        int divideCount = 0;
        mDivideIndexList.clear();
        for (int i = 0; i < sbFormat.length(); i++) {
            if (sbFormat.charAt(i) == formatDivide) {
                mDivideIndexList.add(i - 1 - divideCount);
                divideCount++;
            }
        }
        mWithoutDivideLength = sbFormat.length() - divideCount;
    }

    /**
     * 初始化输入类型
     */
    private void initContentType() {
        String digits = null;
        if (mContentType == TYPE_CUSTOM) {
            parseFormat(mFormatStr);
            digits = "0123456789ABCDEFGHIGKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz" + mDivideStr;
            setInputType(InputType.TYPE_CLASS_TEXT);
        } else if (mContentType == TYPE_PHONE) {
            mMaxLength = 13;
            mWithoutDivideLength = 11;
            digits = "0123456789" + mDivideStr;
            mDivideIndexList.clear();
            mDivideIndexList.add(2);
            mDivideIndexList.add(6);
            setInputType(InputType.TYPE_CLASS_NUMBER);
        } else if (mContentType == TYPE_BANKCARD) {
            mMaxLength = 23;
            mWithoutDivideLength = 19;
            digits = "0123456789" + mDivideStr;
            mDivideIndexList.clear();
            mDivideIndexList.add(3);
            mDivideIndexList.add(7);
            mDivideIndexList.add(11);
            mDivideIndexList.add(15);
            setInputType(InputType.TYPE_CLASS_NUMBER);
        } else if (mContentType == TYPE_IDCARD) {
            mMaxLength = 21;
            mWithoutDivideLength = 18;
            digits = "0123456789xX" + mDivideStr;
            mDivideIndexList.clear();
            mDivideIndexList.add(5);
            mDivideIndexList.add(9);
            mDivideIndexList.add(13);
            setInputType(InputType.TYPE_CLASS_TEXT);
        } else if (mContentType == TYPE_ISBN) {
            // 000*0*0000*0000*0
            // 图书类代码-地区代码-出版社-书序码-校验码
            mMaxLength = 17;
            mWithoutDivideLength = 13;
            digits = "0123456789" + mDivideStr;
            mDivideIndexList.clear();
            mDivideIndexList.add(2);
            mDivideIndexList.add(3);
            mDivideIndexList.add(7);
            mDivideIndexList.add(11);
            mDivideIndexList.add(12);
            setInputType(InputType.TYPE_CLASS_NUMBER);
        }

        // setKeyListener要在setInputType后面调用，否则无效
        if (digits != null) {
            setKeyListener(DigitsKeyListener.getInstance(digits));
        }

        setFilters(new InputFilter[]{new InputFilter.LengthFilter(mMaxLength)});
    }

    /**
     * 判断指定位置是否应该是分隔符
     *
     * @param index 指定位置的索引
     * @return true：应该是分隔符；false：不应该是分隔符
     */
    private boolean needDivide(int index) {
        return mDivideIndexList.contains(index);
    }

    /**
     * 设置输入类型
     *
     * @param contentType 输入类型
     */
    public void setContentType(int contentType) {
        this.mContentType = contentType;
        initContentType();
    }

    /**
     * 获取分隔符
     *
     * @return 分隔符
     */
    public String getDivideStr() {
        return mDivideStr;
    }

    /**
     * 设置分隔符
     *
     * @param divideStr 分隔符
     */
    public void setDivideStr(String divideStr) {
        if (TextUtils.isEmpty(divideStr)) {
            return;
        }
        this.mDivideStr = divideStr;
        initContentType();
    }

    /**
     * 获取无分隔符的完整字符串
     *
     * @return 无分隔符的完整字符串
     */
    public String getTextWithoutDivide() {
        return super.getText().toString().replace(mDivideStr, "");
    }

    /**
     * 判断当前文本是否符合规则
     *
     * @return true：符合；false：不符合
     */
    public boolean isContentCheck() {
        String withoutDivideStr = getTextWithoutDivide();
        return !TextUtils.isEmpty(withoutDivideStr) && withoutDivideStr.length() == mWithoutDivideLength;
    }

    private final TextWatcher mTextWatcher = new TextWatcher() {
        boolean isMiddle;   // 操作的是中间位置
        boolean isMultiple; // 多字符操作
        boolean isAdd;      // 增加字符

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            isMultiple = count > 1 || after > 1;
            isAdd = after > 0;
            if (isAdd) {
                isMiddle = start < s.length();
            } else {
                isMiddle = start < s.length() - 1;
            }
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
        }

        @Override
        public void afterTextChanged(Editable s) {
            if (s == null) {
                return;
            }

            String newStr = s.toString();
            newStr = newStr.replace(mDivideStr, "");

            removeTextChangedListener(mTextWatcher);
            if (isMiddle || isMultiple) {
                // 在中间插入或一次性粘贴多字符，需要全部重新计算
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < newStr.length(); i++) {
                    sb.append(newStr.charAt(i));
                    // 判断该索引后边是否需要添加分隔符
                    if (needDivide(i)) {
                        sb.append(mDivideStr);
                    }
                }
                s.replace(0, s.length(), sb);
            } else {
                if (isAdd) {
                    // 在末尾增加一个字符
                    if (needDivide(newStr.length() - 1)) {
                        if (!s.toString().endsWith(mDivideStr)) {
                            s.append(mDivideStr);
                        } else if (mDivideStr.endsWith(s.toString().substring(s.length() - 2 * mDivideStr.length(), s.length() - mDivideStr.length()))) {
                            s.delete(s.length() - mDivideStr.length(), s.length());
                        }
                    } else if (s.toString().endsWith(mDivideStr)) {
                        s.delete(s.length() - mDivideStr.length(), s.length());
                    }
                } else {
                    // 在末尾删除一个字符
                    if (!s.toString().endsWith(mDivideStr) && needDivide(newStr.length() - 1)) {
                        s.delete(s.length() - mDivideStr.length(), s.length());
                    }
                }
            }
            addTextChangedListener(mTextWatcher);

            if (isContentCheck() && mOnInputCheckSuccessListener != null) {
                mOnInputCheckSuccessListener.onInputCheckSuccess(getTextWithoutDivide());
            }
        }
    };

    public void setOnInputCheckSuccessListener(OnInputCheckSuccessListener onInputCheckSuccessListener) {
        mOnInputCheckSuccessListener = onInputCheckSuccessListener;
    }
}